<template>
  <div class="goods-sku">
    <dl v-for='(item, index) in specs' :key='index'>
      <dt>{{item.name}}</dt>
      <dd>
        <template v-for='(tag, i) in item.values' :key='i'>
          <img @click='toggle(tag, item.values)' :class='{selected: tag.selected, disabled: tag.disabled }' v-if='tag.picture' :src="tag.picture" alt="">
          <span @click='toggle(tag, item.values)' :class='{selected: tag.selected, disabled: tag.disabled }' v-else>{{tag.name}}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>
<script>
// 导入函数：用于计算集合的笛卡尔集
import powerSet from '@/vendor/power-set.js'
const spliter = '※'

// 更新规格的禁用状态
// 1. 页面首次渲染时触发
// 2. 点击规格的时候重新触发
const updateDisabledStatus = (specs, pathMap) => {
  // 每一种规格都单独判断一遍
  specs.forEach((item, index) => {
    // 获取所有规格选中的值 selectedValues = [蓝色, undefined, undefined]
    const selectedValues = getSelectedValues(specs)
    item.values.forEach(tag => {
      // 判断每一个规格是否可以点击（是否在pathMap里面）
      if (tag.selected) {
        return
      } else {
        // 模拟选中一个值
        selectedValues[index] = tag.name
      }
      // console.log(selectedValues)
      // 判断你选中的值是否在pathMap里面
      const pathKey = selectedValues.filter(item => item).join(spliter)
      // 如果pathKey不再pathMap里面应该被禁用
      tag.disabled = !pathMap[pathKey]
    })
  })
}

// 封装一个函数，获取所有的规格的选中的值
const getSelectedValues = (specs) => {
  const result = []
  specs.forEach((item, index) => {
    const tag = item.values.find(tag => tag.selected)
    if (tag) {
      // 获取了选中的规格信息
      result[index] = tag.name
    } else {
      // 没有选中的值设置为undefined
      result[index] = undefined
    }
  })
  // result = ['黑色', undefined, '30cm']
  return result
}

// 封装一个函数，根据skus所有的数据生成路径字典
const usePathMap = (skus) => {
  // 最终的路径字典
  const pathMap = {}
  skus.forEach(sku => {
    // 过滤掉无效的sku
    if (sku.inventory === 0) return
    // 获取规格的集合
    // skuSpec = ['蓝色', '中国', '10cm']
    const skuSpec = sku.specs.map(tag => tag.valueName)
    // 计算sku规格组合的笛卡尔集
    const specSet = powerSet(skuSpec)
    // 把笛卡尔集中的每一项组合成字典的key放到字典对象中
    specSet.forEach(spec => {
      // 去掉空数组
      if (spec.length === 0) return
      // mapKey = '蓝色※中国'
      const mapKey = spec.join(spliter)
      // 把该规格组合放到字典里面
      // pathMap = { '蓝色※中国': [123123123123123, 12312312312312]}
      if (pathMap[mapKey]) {
        // 该规格组合已经存在
        pathMap[mapKey].push(sku.id)
      } else {
        // 该规格组合尚未存在
        pathMap[mapKey] = [sku.id]
      }
    })
  })
  return pathMap
}

// 根据skuId控制规格的选中
const initSkuIdSelected = (skuId, specs, skus) => {
  // 目标：需要选中的规格
  const target = skus.find(item => item.id === skuId).specs
  specs.forEach(item => {
    // 控制每一种规格的选中：颜色；产地；尺寸
    // 获取颜色、产地或者尺寸
    const currentSpec = target.find(tag => tag.name === item.name)
    item.values.forEach(tag => {
      // 此时tag中的黑色还是蓝色被选中？
      if (tag.name === currentSpec.valueName) {
        // 当前的标签名称和目标名称相同
        tag.selected = true
      }
    })
  })
}

export default {
  name: 'GoodsSku',
  props: {
    skuId: {
      type: String,
      default: ''
    },
    specs: {
      type: Array,
      default: () => []
    },
    skus: {
      type: Array,
      default: () => []
    }
  },
  setup (props) {
    const pathMap = usePathMap(props.skus)

    // 组件初始化的时候，判断skuId是否存在，如果存在就控制选中
    if (props.skuId) {
      initSkuIdSelected(props.skuId, props.specs, props.skus)
    }

    // 页面首次渲染时触发
    updateDisabledStatus(props.specs, pathMap)

    // 控制规格选项的选中和取消
    const toggle = (tag, list) => {
      // 如果该按钮是禁用状态，不可以点击
      if (tag.disabled) return
      // 需求：选中当前的选项，其他的选项需要取消选中
      // 1. 把所有的标签都取消选中
      list.forEach(item => {
        if (item !== tag) {
          // 排除当前点击的标签：其余的都取消选中
          item.selected = false
        }
      })
      // 2. 当前点击的标签单独控制
      tag.selected = !tag.selected

      // const ret = getSelectedValues(props.specs)
      // console.log(ret)
      // 点击标签的时候，判断规格是否被禁用
      updateDisabledStatus(props.specs, pathMap)
    }
    return { toggle }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
